package gat.application.backgroundUser.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bitsun.core.common.constant.RuntimeContextHolder;
import com.bitsun.core.common.enums.UserTypeEnum;
import com.bitsun.core.common.exception.AppException;
import com.bitsun.core.common.exception.ErrorCode;
import com.bitsun.core.common.persistence.BasePService;
import com.bitsun.core.common.persistence.IPService;
import com.bitsun.core.common.persistence.Pager;
import com.bitsun.core.common.persistence.QueryParamUtils;
import com.bitsun.core.common.util.MD5Util;
import com.bitsun.core.common.web.CurrentUser;
import gat.RedisService;
import gat.application.backgroundUser.BackgroundUserService;
import gat.application.backgroundUser.RoleService;
import gat.application.backgroundUser.UserRoleService;
import gat.application.tg.TgBotService;
import gat.application.tg.UserBotService;
import gat.common.constant.RedisNoConstants;
import gat.common.enums.NoEnum;
import gat.common.exception.ExceptionEnum;
import gat.common.util.ConditionUtil;
import gat.common.util.ExceptionUtil;
import gat.common.util.JwtUtil;
import gat.common.util.PasswordCheckUtil;
import gat.convertor.backgroundUser.BackgroundUserReqDtoConvertor;
import gat.convertor.backgroundUser.BackgroundUserResDtoConvertor;
import gat.dto.req.backgroundUser.BackgroundUserReqDto;
import gat.dto.req.backgroundUser.BackgroundUserReqParams;
import gat.dto.res.backgroundUser.BackgroundUserResDto;
import gat.dto.res.backgroundUser.RoleResDto;
import gat.dto.res.tg.TgBotResDto;
import gat.dto.res.tg.UserBotResDto;
import gat.infrastructure.persistence.dao.backgroundUser.BackgroundUserMapper;
import gat.infrastructure.persistence.dao.backgroundUser.UserRoleMapper;
import gat.infrastructure.persistence.po.backgroundUser.BackgroundUserPo;
import gat.infrastructure.persistence.po.backgroundUser.UserRolePo;
import gat.infrastructure.persistence.po.tg.UserBotPo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;
/**
 * 示例表，应用（业务编排）层实现
 * @author: tmac
 * @email: tmac
 */
@Slf4j
@Service("backgroundUserAppService")
@Transactional(rollbackFor = Exception.class)
public class BackgroundUserServiceImpl implements BackgroundUserService {

    @Autowired
    private BackgroundUserReqDtoConvertor backgroundUserReqDtoConvertor;

    @Autowired
    private BackgroundUserResDtoConvertor backgroundUserResDtoConvertor;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisService redisService;

    @Autowired
    private BackgroundUserMapper backgroundUserMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private TgBotService tgBotService;

    @Autowired
    private UserBotService userBotService;

    private IPService<BackgroundUserPo> backgroundUserPoService;

    @SuppressWarnings("SpringJavaAutowiringInspection")
    public BackgroundUserServiceImpl(BackgroundUserMapper backgroundUserMapper) {
        this.backgroundUserPoService = new BasePService(backgroundUserMapper);
    }



    @Override
    public BackgroundUserResDto save(BackgroundUserReqDto reqDto) {

        //checkCode(reqDto.getPhone(),reqDto.getCode());
        ConditionUtil.mustNotBlank(reqDto.getPhone(), ExceptionEnum.EXCEPTION_ENUM_10002);
        BackgroundUserPo userPo = backgroundUserPoService.getOne(new LambdaQueryWrapper<BackgroundUserPo>()
                .eq(BackgroundUserPo::getUsername, reqDto.getPhone()));
        BackgroundUserPo one = backgroundUserPoService.getOne(new LambdaQueryWrapper<BackgroundUserPo>()
                .eq(BackgroundUserPo::getNickname, reqDto.getNickname()));
        if (Objects.nonNull(one)){
            ExceptionUtil.throwNew(ExceptionEnum.EXCEPTION_ENUM_10034);
        }
        if(Objects.nonNull(userPo)){
            ExceptionUtil.throwNew(ExceptionEnum.EXCEPTION_ENUM_10023);
        }
        BackgroundUserPo po = backgroundUserReqDtoConvertor.dto2Po(reqDto);
        String userCode = redisService.getNo(NoEnum.NO_PIR);
        po.setPassword(MD5Util.MD5Upper("tgBot123456"));
        po.setUserCode(userCode);
        po.setUsername(reqDto.getPhone());
        po.setHeadPic("https://6871test.oss-cn-hangzhou.aliyuncs.com/head.png");
        backgroundUserPoService.save(po);
        BackgroundUserResDto resDto = backgroundUserResDtoConvertor.po2Dto(po);

        // 保存用户角色表
        reqDto.getRoleIds().forEach(roleId -> {
            UserRolePo userRolePo = new UserRolePo();
            userRolePo.setUserId(resDto.getId());
            userRolePo.setRoleId(roleId);
            userRoleMapper.insert(userRolePo);
        });
        return resDto;
    }
    //验证码校验
    private void  checkCode(String phone, String code) {
        String msg = redisService.get(RedisNoConstants.SMS_CODE + phone);
        ConditionUtil.mustNotNull(msg, ExceptionEnum.EXCEPTION_ENUM_10003);
        ConditionUtil.mustNotBlank(code, ExceptionEnum.EXCEPTION_ENUM_10004);
        ConditionUtil.mustEquals(msg, code, ExceptionEnum.EXCEPTION_ENUM_10005);
    }

    @Override
    public boolean deleteByIds(String ids) {
        BackgroundUserPo userPo = backgroundUserPoService.getById(Long.valueOf(ids));
        try {
            List<Long> idLongList =
            Arrays.asList(ids.split(",")).stream().map(s -> NumberUtils.createLong(s.trim())).collect(Collectors.toList());
            return backgroundUserPoService.removeByIds(idLongList);
        } catch (Exception e) {
            throw new AppException("参数错误：" + ids, ErrorCode.pc("417"), e);
        }
     }

    @Override
    public Pager<BackgroundUserResDto> doPager(Map<String, Object> params) {
        Pager<BackgroundUserPo> poPager = backgroundUserPoService.queryPage(params, BackgroundUserPo.class);
        Pager<BackgroundUserResDto> resDtoPager = backgroundUserResDtoConvertor.convertPoPager2ResDtoPager(poPager);
        return resDtoPager;
    }

    @Override
    public BackgroundUserResDto selectOne(Long id) {
        BackgroundUserPo po = backgroundUserPoService.getById(id);
        BackgroundUserResDto resDto = backgroundUserResDtoConvertor.po2Dto(po);
        List<RoleResDto> roles = userRoleService.getUserRoleById(id);
        if (Objects.nonNull(resDto)){
            resDto.setRoleList(roles);
        }
        return resDto;
    }

    @Override
    public BackgroundUserResDto selectOne(Map<String, Object> params) {
        QueryWrapper queryWrapper = QueryParamUtils.queryWrapper4eq(BackgroundUserPo::new, params);
        queryWrapper.last(" limit 1");
        BackgroundUserPo po = backgroundUserPoService.getOne(queryWrapper);
        BackgroundUserResDto resDto = backgroundUserResDtoConvertor.po2Dto(po);
        return resDto;
    }


    @Override
    public boolean updateProps(Long id, BackgroundUserReqDto reqDto) {
        BackgroundUserPo po = backgroundUserReqDtoConvertor.dto2Po(reqDto);
        po.setId(id);
        BackgroundUserPo userPo = backgroundUserPoService.getById(id);
       if(StringUtils.isNotEmpty(reqDto.getNickname())){
           if(!StringUtils.equals(userPo.getNickname(),reqDto.getNickname())){
               BackgroundUserPo one = backgroundUserPoService.getOne(new LambdaQueryWrapper<BackgroundUserPo>()
                       .eq(BackgroundUserPo::getNickname, reqDto.getNickname()));
               if (Objects.nonNull(one)){
                   ExceptionUtil.throwNew(ExceptionEnum.EXCEPTION_ENUM_10034);
               }
           }
       }
        if(StringUtils.isNotEmpty(reqDto.getPhone())){
            if(!StringUtils.equals(userPo.getPhone(),reqDto.getPhone())){
                BackgroundUserPo two = backgroundUserPoService.getOne(new LambdaQueryWrapper<BackgroundUserPo>()
                        .eq(BackgroundUserPo::getPhone, reqDto.getPhone()));
                if (Objects.nonNull(two)){
                    ExceptionUtil.throwNew(ExceptionEnum.EXCEPTION_ENUM_10023);
                }
                if (!userPo.getUsername().equals("admin")){
                    po.setUsername(po.getPhone());
                }

            }

        }
        if (StringUtils.isNotEmpty(reqDto.getUsername())) {
            throw new AppException("不允许修改用户名");
        }
        backgroundUserPoService.updateById(po);

        if (CollectionUtil.isNotEmpty(reqDto.getRoleIds())) {
            List<UserRolePo> userRolePos = userRoleMapper.selectList(new LambdaQueryWrapper<UserRolePo>()
                    .eq(UserRolePo::getUserId, id)
            );
            if (CollectionUtil.isNotEmpty(userRolePos)) {
                userRolePos.forEach(userRolePo -> {
                    userRoleMapper.deleteById(userRolePo.getId());
                });
                reqDto.getRoleIds().forEach(roleId -> {
                    UserRolePo userRolePo = new UserRolePo();
                    userRolePo.setUserId(id);
                    userRolePo.setRoleId(roleId);
                    userRoleMapper.insert(userRolePo);
                });
            }
        }
        return backgroundUserPoService.updateById(po);
    }

    @Override
    public Pager<BackgroundUserResDto> getBackgroundUserList(BackgroundUserReqParams params) {
        Page  page = new Page(params.getCurrentPage(), params.getPageSize());
        IPage<BackgroundUserResDto> iPage = backgroundUserMapper.getBackgroundUserList(page, params);
        iPage.getRecords().forEach( u -> {
            if (StringUtils.isNotBlank(u.getRoleId())){
                List<Long> idLongList =
                        Arrays.asList(u.getRoleId().split(",")).stream().map(s -> NumberUtils.createLong(s.trim())).collect(Collectors.toList());
                List<RoleResDto> resDtos = roleService.getByRoleIds(idLongList);
                u.setRoleList(resDtos);
            }
            // 查询关联机器人
            UserBotResDto userBotResDto = userBotService.getUserBotByUserCode(u.getUserCode());
            if (userBotResDto != null) {
                TgBotResDto tgBotByBotUni = tgBotService.getTgBotByBotUni(userBotResDto.getBotId());
                if (tgBotByBotUni != null) {
                    u.setBotName(tgBotByBotUni.getBotName());
                }
            }

        });
        return new Pager<>(iPage.getRecords(), iPage.getTotal(), params.getPageSize(), params.getCurrentPage());
    }

    public static void main(String[] args) {
        String s = MD5Util.MD5Upper("123456");
        System.out.println(s);
    }

    @Override
    public BackgroundUserResDto login(BackgroundUserReqParams params) {
        BackgroundUserPo user = backgroundUserPoService.getOne(new QueryWrapper<BackgroundUserPo>().lambda()
                .eq(BackgroundUserPo::getUsername,params.getUsername()));
        ConditionUtil.mustNotNull(user,ExceptionEnum.EXCEPTION_ENUM_10008);
        ConditionUtil.mustNotBlank(params.getPassword(), ExceptionEnum.EXCEPTION_ENUM_10001);
        params.setPassword(MD5Util.MD5Upper(params.getPassword()));
        ConditionUtil.mustEquals(params.getPassword(),user.getPassword(),ExceptionEnum.EXCEPTION_ENUM_10008);
        BackgroundUserResDto resDto = backgroundUserResDtoConvertor.po2Dto(user);
        resDto.setToken(createToken(resDto));
        return resDto;
    }

    @Override
    public Boolean updatePassword(BackgroundUserReqParams params) {
        BackgroundUserPo user = backgroundUserPoService.getOne(new QueryWrapper<BackgroundUserPo>().lambda()
                .eq(BackgroundUserPo::getUsername,params.getUsername()));
        ConditionUtil.mustNotNull(user,ExceptionEnum.EXCEPTION_ENUM_10007);
        ConditionUtil.mustNotBlank(params.getPassword(), ExceptionEnum.EXCEPTION_ENUM_10001);
        PasswordCheckUtil.checkPassword(params.getPassword());
        user.setPassword(MD5Util.MD5Upper(params.getPassword()));
        return backgroundUserPoService.updateById(user);
    }

    @Override
    public Boolean resetPassword(BackgroundUserReqParams params) {
        // checkCode(params.getPhone(), params.getCode());
        BackgroundUserPo user = backgroundUserPoService.getOne(new QueryWrapper<BackgroundUserPo>().lambda()
                .eq(BackgroundUserPo::getUserCode,params.getUserCode()));
        ConditionUtil.mustNotNull(user,ExceptionEnum.EXCEPTION_ENUM_10007);
        ConditionUtil.mustNotBlank(params.getPassword(), ExceptionEnum.EXCEPTION_ENUM_10001);
        PasswordCheckUtil.checkPassword(params.getPassword());
        user.setPassword(MD5Util.MD5Upper(params.getPassword()));
        return backgroundUserPoService.updateById(user);
    }

    @Override
    public BackgroundUserResDto loginByPhone(BackgroundUserReqParams params) {
        //todo  谷歌验证去掉
        checkCode(params.getPhone(), params.getCode());
        BackgroundUserPo user = backgroundUserPoService.getOne(new QueryWrapper<BackgroundUserPo>().lambda()
                .eq(BackgroundUserPo::getPhone,params.getPhone()));
        ConditionUtil.mustNotNull(user,ExceptionEnum.EXCEPTION_ENUM_10007);
//        Boolean boo = googleAuthenticatorService.validateCode(DesUtil.getDecryptString(user.getSecretKey()), params.getSecretCode());
//        if (!boo){
//            ExceptionUtil.throwNew(ExceptionEnum.EXCEPTION_ENUM_10038);
//        }
        BackgroundUserResDto resDto = backgroundUserResDtoConvertor.po2Dto(user);
        resDto.setToken(createToken(resDto));
        return resDto;
    }

    @Override
    public void signOut() {
        Long  id = RuntimeContextHolder.currentRuntimeContext().getCurrentUser().getId();
        redisService.del(RedisNoConstants.token + id);
    }

    @Override
    public Boolean sendSMS(String phone) {
        return true;
    }

    private String createToken(BackgroundUserResDto resDto) {
        CurrentUser user = new CurrentUser();
        user.setId(resDto.getId());
        user.setUserCode(resDto.getUserCode());
        user.setUsername(resDto.getUsername());
        user.setNickname(resDto.getNickname());
        user.setPhone(resDto.getPhone());
        user.setUserType(UserTypeEnum.ADMIN.getCode());
        String token = JwtUtil.backGroundUserCreateToken(user);
        redisService.set(RedisNoConstants.token + resDto.getId(), token, 4* 3600L);
        return token;
    }

}